#include <cmath>
#include "typedef.h"
#include "xyz.h"


#ifndef _KUAI_PBC_H_
#define _KUAI_PBC_H_


namespace kuai {

	class PBC {
	public:
		explicit PBC();
		explicit PBC(const RealNumber& a, const RealNumber& b, const RealNumber& c);
		explicit PBC(const RealNumber& a, const RealNumber& b, const RealNumber& c, const RealNumber& alpha, const RealNumber& beta, const RealNumber& gamma);

	public:
		RealNumber a() const {
			return fabs(ax);
		}
		RealNumber b() const {
			return sqrt(bx*bx + by*by);
		}
		RealNumber c() const {
			return sqrt(cx*cx + cy*cy + cz*cz);
		}

		XYZ va() const {
			return XYZ(ax, 0, 0);
		}

		XYZ vb() const {
			return XYZ(bx, by, 0);
		}

		XYZ vc() const {
			return XYZ(cx, cy, cz);
		}

		RealNumber alpha() const {
			return angle(vb(), vc());
		};
		RealNumber beta() const {
			return acos(cx/c());
		}
		RealNumber gamma() const {
			return atan2(by, bx);
		}

		RealNumber volumn() const {
			return ax * by * cz;
		}

		void update(XYZ& v) const;

		XYZ image(const XYZ& v) const {
			XYZ result(v);
			update(result);
			return result;
		};

		void scaleX(RealNumber factor) {
			ax *= factor; bx*= factor; cx *= factor;
		};
		void scaleY(RealNumber factor) {
			by *= factor; cy *= factor;
		};
		void scaleZ(RealNumber factor) {
			cz *= factor;
		};

		void scale(RealNumber x, RealNumber y, RealNumber z) {
			scaleX(x);
			scaleY(y);
			scaleZ(z);
		}

		void scale(RealNumber factor) {
			scale(x, y, z);
		}

	private:
		RealNumber ax, bx, by, cx, cy, cz;
	};

}

#endif

